/**
 * 
 */
package org.gbif.wdpa.utils;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.math.BigDecimal;
import java.math.MathContext;

/**
 * This is a utility class that will create text files for input to mysql (maybe PostGIS)
 * that represent a grid.
 * Grids are configurable in size (10 degree etc) with the input parameters
 * @author tim
 */
public class GridBuilder {
	protected static final int ROWS_PER_STATEMENT = 10000;
	
	protected static void writeGridFile(double degreesPerGridDouble, String table, Writer output) throws IOException {
		int r =new Double(360.0/degreesPerGridDouble).intValue();
		if ((double) r * degreesPerGridDouble != 360.0){
			System.err.println(degreesPerGridDouble + " must divide into 360");
			System.err.println("(But remainder is " + 360%degreesPerGridDouble + ")");
			return;
		}
		
		int gridsPerRow = new Double((360/degreesPerGridDouble)).intValue();
		int gridsPerColumn = gridsPerRow/2;
		int gridCount = gridsPerColumn * gridsPerRow;
		System.out.println("DegreesPerGrid[" + degreesPerGridDouble + "] matrix[" + gridsPerRow + " x " + gridsPerColumn + "] gridCount[" + gridCount + "]");
		
		int rowCount = 0;
		BigDecimal latitude = new BigDecimal(-90,  MathContext.DECIMAL32);
		BigDecimal longitude = new BigDecimal(-180,  MathContext.DECIMAL32);
		BigDecimal degreesPerGrid = new BigDecimal(degreesPerGridDouble,  MathContext.DECIMAL32);
		int gridId = 0;
		for (long i=0; i<gridCount; i++) {
			
			// we create a new statement every ROWS_PER_STATEMENT rows
			if (i%ROWS_PER_STATEMENT == 0) {
				output.write("insert into " + table + "(id, minX, maxX, minY, maxY, the_geom) values \n");
			}
			
			if (i%gridsPerRow == 0) {
				System.out.print("\nRow" + rowCount +": ");
				rowCount++;
				longitude= new BigDecimal(-180,  MathContext.DECIMAL32);;
				if (gridId!=0) {
					latitude = latitude.add(degreesPerGrid);
				}
			}
			
			//System.out.print("[" + gridId + " - [" + latitude + ", " + (latitude+degreesPerGrid) + ", " + longitude + ", " + (longitude+degreesPerGrid) + "]] ");
			output.write("(" 
						+ gridId +","
						+ latitude +","
						+ (latitude.add(degreesPerGrid)) 
						+","+ longitude 
						+","+ (longitude.add(degreesPerGrid)) 
						+",GeomFromText('POLYGON(( " +
								longitude + " " + latitude + ", " +
								longitude + " " + (latitude.add(degreesPerGrid)) + ", " +
								(longitude.add(degreesPerGrid)) + " " + (latitude.add(degreesPerGrid)) + ", " +
								(longitude.add(degreesPerGrid)) + " " + latitude + ", " +
								longitude + " " + latitude + "))', 4326)"
					+")");
			
			// close the new statement on ROWS_PER_STATEMENT rows
			if ((i+1)%ROWS_PER_STATEMENT==0) {
				output.write(";\n");
			} else {
				if (i+1<gridCount) {
					output.write(",\n"); 
				} else {
					output.write("\n");
				}
			}
			
			longitude = longitude.add(degreesPerGrid);
			gridId++;
			
		}
		output.write(";\n");
	}
	
	protected static void writeTable(String tableName, Writer writer) throws IOException {
		StringBuffer sb = new StringBuffer();
		sb.append("create table " + tableName + "(\n");
		sb.append("id int not null, minX decimal(11,8) not null, maxX decimal(11,8) not null, minY decimal(11,8) not null, maxY decimal(11,8) not null, the_geom geometry, primary key (id)");
		sb.append("\n);\n\n");
		writer.write(sb.toString());
	}
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		try {
			if (args.length!=3) {
				System.out.println("usage: tableName outputFile size");
				return;
			}
			String tableName = args[0];
			String outputFile = args[1];
			String gridSizeAsString = args[2];
			double gridSize = Double.parseDouble(gridSizeAsString);
			
			
			Writer w = new BufferedWriter(new FileWriter(outputFile));
			//writeTable(tableName, w);
			//w.flush();
			writeGridFile(gridSize, tableName, w);
			w.flush();
			w.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
